#!/usr/bin/python

# This script is intented to check if no file has been forgoten in a CMakeLists
# It take a directory as sole argument and goes through the hierarchy.
# For each sub-directory containing a CMakeLists, it checks if every recognized
# source file has been added to the CMakeLists
# It collects the following information :
#	- The directory has a CMakeLists ?
#	- The CMakeLists contains source variables (HEADERS, SOURCES, INLINES,
#		HEADERS_TO_MOC)
#	- There is source files that are missing in the source variables

import sys
import string
import os.path
from os import listdir

cmakeFileName = 'CMakeLists.txt'

def usage():

	return 'Usage:\n\t' + sys.argv[0] + ' <path>'

def getToken(f):
	whitespaces = string.whitespace
	separators = [' ', '\t', '\n', '\v']
	specialToken = [ '(', ')', '']
	c = f.read(1)
	token = ''
	#print c
	while c in separators:
		c = f.read(1)
	while c not in separators:
		if c in specialToken:
			if token == '':
				return c
			else:
				# Go one byte backward
				f.seek(-1, 1)
				return token
		else:
			token += c
		c = f.read(1)
	return token


class ParseError(Exception):
	def __init__(self, value):
		self.value = value

def checkIdentifier(identifier):
	return identifier in ['HEADERS', 'INLINES', 'SOURCES', 'HEADERS_TO_MOC', 'XIBS']

def readSetCommand(f):
	token = getToken(f)
	if token != '(':
		print 'Error parsing file'
	else:
		varName = ''
		# Get the variable name
		token = getToken(f)
		if checkIdentifier(token):
			varName = token
			token = getToken(f)
			resList = []
			while token != '' and token != ')':
				resList.append(token)
				token = getToken(f)
			if token != ')':
				print "Wrong 'set' command"
			return [varName, resList]

def getFilesWithExtensions(content, extList):
	resList =[]
	for f in content:
		name, ext = os.path.splitext(f)
		if ext in extList:
			resList.append(f)
	return resList

def analyseDirectory(path):
	content = listdir(path)
	try:
		f = open(path + '/' + cmakeFileName)
	except IOError:
		print 'No CMakeLists found.'
		return
	token = getToken(f)
	while token != '':
		if token == 'set':
			l = readSetCommand(f)
			# The set command is one we want to check
			if l:
				fileList = []
				# Build the list of file from the directory
				if l[0] == 'HEADERS' or l[0] == 'HEADERS_TO_MOC':
					fileList = getFilesWithExtensions(content, ['.h', '.hpp'])
				elif l[0] == 'SOURCES':
					fileList = getFilesWithExtensions(content, ['.cpp', '.cc', '.c', '.m', '.mm'])
				elif l[0] == 'INLINES':
					fileList = getFilesWithExtensions(content, ['.inl'])
				elif l[0] == 'XIBS':
					fileList = getFilesWithExtensions(content, ['.xib', '.storyboard'])
				else:
					print 'Identifier not handled'
				#print fileList
				resList = []
				# Check that every file is referenced in the CMakeLists
				for fileName in fileList:
					if not fileName in l[1]:
						resList.append(fileName)
				if len(resList) > 0:
					print 'Element(s) missing in ' + l[0]
					print resList
				else:
					print "Nothing missing in " + l[0]
		token = getToken(f)

def main():
	if (len(sys.argv) > 1):
		p = sys.argv[1]
		if (os.path.isdir(p)):
			analyseDirectory(sys.argv[1])
		else:
			print p + ' is not a directory.'
	else:
		print usage()

main()
